package org.hhf.core;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * ListRedis类实现了Redis的列表数据类型操作
 */
public class ListRedis {
    private final RedisCore core;
    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public ListRedis(RedisCore core) {
        this.core = core;
    }

    /**
     * 获取列表，如果不存在则创建
     */
    @SuppressWarnings("unchecked")
    private LinkedList<String> getOrCreateList(String key) {
        Object value = core.get(key);
        if (value == null || !(value instanceof LinkedList)) {
            LinkedList<String> list = new LinkedList<>();
            core.put(key, list, RedisCore.DataType.LIST);
            return list;
        }
        return (LinkedList<String>) value;
    }

    /**
     * 从左侧推入元素
     */
    public Long lpush(String key, String... values) {
        lock.writeLock().lock();
        try {
            LinkedList<String> list = getOrCreateList(key);
            for (String value : values) {
                list.addFirst(value);
            }
            return (long) list.size();
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 从右侧推入元素
     */
    public Long rpush(String key, String... values) {
        lock.writeLock().lock();
        try {
            LinkedList<String> list = getOrCreateList(key);
            for (String value : values) {
                list.addLast(value);
            }
            return (long) list.size();
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 从左侧弹出元素
     */
    public String lpop(String key) {
        lock.writeLock().lock();
        try {
            LinkedList<String> list = getOrCreateList(key);
            if (list.isEmpty()) {
                return null;
            }
            return list.removeFirst();
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 从右侧弹出元素
     */
    public String rpop(String key) {
        lock.writeLock().lock();
        try {
            LinkedList<String> list = getOrCreateList(key);
            if (list.isEmpty()) {
                return null;
            }
            return list.removeLast();
        } finally {
            lock.writeLock().unlock();
        }
    }

    /**
     * 获取列表的指定范围
     */
    public List<String> lrange(String key, long start, long end) {
        lock.readLock().lock();
        try {
            LinkedList<String> list = getOrCreateList(key);
            int size = list.size();
            
            // 处理负索引
            if (start < 0) {
                start = Math.max(0, size + start);
            }
            if (end < 0) {
                end = size + end;
            }
            
            // 确保索引有效
            if (start >= size || end < 0 || start > end) {
                return Collections.emptyList();
            }
            
            // 调整结束索引不超过列表大小
            end = Math.min(end, size - 1);
            
            return new ArrayList<>(list.subList((int) start, (int) end + 1));
        } finally {
            lock.readLock().unlock();
        }
    }

    /**
     * 阻塞式左侧弹出
     */
    public String blpop(String key, long timeout) throws InterruptedException {
        long startTime = System.currentTimeMillis();
        long remainingTime = timeout * 1000;
        
        while (true) {
            lock.writeLock().lock();
            try {
                LinkedList<String> list = getOrCreateList(key);
                if (!list.isEmpty()) {
                    return list.removeFirst();
                }
                
                // 如果超时时间为0，则无限等待
                if (timeout == 0) {
                    lock.writeLock().unlock();
                    Thread.sleep(100);
                    continue;
                }
                
                // 检查是否超时
                long elapsedTime = System.currentTimeMillis() - startTime;
                remainingTime = timeout * 1000 - elapsedTime;
                if (remainingTime <= 0) {
                    return null;
                }
                
                lock.writeLock().unlock();
                Thread.sleep(Math.min(100, remainingTime));
            } finally {
                if (lock.isWriteLockedByCurrentThread()) {
                    lock.writeLock().unlock();
                }
            }
        }
    }

    /**
     * 获取列表长度
     */
    public Long llen(String key) {
        lock.readLock().lock();
        try {
            LinkedList<String> list = getOrCreateList(key);
            return (long) list.size();
        } finally {
            lock.readLock().unlock();
        }
    }
}